/*
 * Copyright 2014 Jonathan Haas
 *
 *    Licensed under the Apache License, Version 2.0 (the "License");
 *    you may not use this file except in compliance with the License.
 *    You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 *    Unless required by applicable law or agreed to in writing, software
 *    distributed under the License is distributed on an "AS IS" BASIS,
 *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *    See the License for the specific language governing permissions and
 *    limitations under the License.
 */

package app.grinreader.model;

import android.graphics.Canvas;
import android.text.TextPaint;

import java.text.BreakIterator;

/**
 *
 */
public class TextElement implements CharSequence, ContentElement {

	private final char[] chars;
	private final int start;
	private final int end;

	public TextElement(String text) {
		chars = text.toCharArray();
		start = 0;
		end = chars.length;
	}

	private TextElement(char[] chars, int start, int end) {
		this.chars = chars;
		this.start = start;
		this.end = end;
	}


	@Override
	public String toString() {
		return new String(chars, start, end-start);
	}

	@Override
	public int length() {
		return end - start;
	}

	@Override
	public char charAt(int index) {
		return chars[index + start];
	}

	@Override
	public TextElement subSequence(int start, int end) {
		return new TextElement(chars, this.start + start, this.start + end);
	}

	@Override
	public void getBreakPosition(float remainingContentSpace, int startPos, TextPaint paint, BreakData result) {
		float[] measuredWidth = new float[1];
//		int r = startPos + paint.breakText(chars, start + startPos, end-startPos-start, remainingContentSpace, measuredWidth);

		int r = startPos + getBreakPos(remainingContentSpace, paint, measuredWidth, start + startPos, end - startPos - start, chars);

		result.setWidth(measuredWidth[0]);
		result.setStartPos(startPos);
		result.setEndPos(length());
		if(r == length()){
			result.setBreakPos(r);
			result.setContentBeforeBreak(subSequence(startPos, r));
			return;
		}
		BreakIterator lineInstance = BreakIterator.getLineInstance();
		lineInstance.setText(toString());
		int p = lineInstance.preceding(r);
		if (p > startPos) {
				result.setBreakPos(p);
				result.setContentBeforeBreak(subSequence(startPos, p));
				return;
		}
		result.setBreakPos(r);
		result.setContentBeforeBreak(subSequence(startPos, r));
	}

	private static int getBreakPos(float remainingContentSpace, TextPaint paint, float[] measuredWidth, int s, int l, char[] c) {
		int res;
		int q = 0;
		while (q + 50 < l){
			res = paint.breakText(c, s, q + 50, remainingContentSpace, measuredWidth);
			if(res != q + 50){
				return res;
			}
			q+=50;
		}
		res = paint.breakText(c, s, l, remainingContentSpace, measuredWidth);
		return res;
	}

	@Override
	public float getWidth(TextPaint paint) {
		return paint.measureText(this, 0, length());
	}

	@Override
	public float getHeight(TextPaint paint) {
		return paint.getFontMetrics(null);
	}

	@Override
	public void draw(Canvas canvas, TextPaint paint, float x, float y) {
		canvas.drawText(this, 0, length(), x,y,paint);
	}
}
